package com.qd.pay.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.CacheKey;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.RedisTemplateUtil;
import com.qd.pay.domain.OrderBodyDTO;
import com.qd.pay.model.OrderBody;
import com.qd.pay.repository.OrderBodyRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.util.Optional;

/**
 * @author sjk
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderBodyService {

    private final OrderBodyRepository orderBodyRepository;
    @Resource
    private RedisTemplateUtil<OrderBody> redisTemplateUtil;

    private static final String PREFIX_ID = "m_order_body_id_{0}";

    @Transactional(rollbackFor = Exception.class)
    public OrderBody save(OrderBody model) throws ApiException {
        try {
            if (!orderBodyRepository.save(model)) {
                throw new ApiException(ApiResult.error());
            }
            return model;
        } finally {
            clearCache(model);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(OrderBody model) throws ApiException {
        final OrderBody historyModel = Optional.ofNullable(getById(model.getId())).orElseThrow(() -> new ApiException("ID不存在,不能更新"));
        try {
            if (!orderBodyRepository.updateById(model)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean removeById(String id) throws ApiException {
        final OrderBody historyModel = Optional.ofNullable(getById(id)).orElseThrow(() -> new ApiException("ID不存在,不能删除"));
        try {
            if (!orderBodyRepository.removeById(id)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    public Boolean isExists(String id) {
        return orderBodyRepository.isExists(id);
    }

    public OrderBody getById(String id) {
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, id);
        return redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY), () -> orderBodyRepository.getById(id), OrderBody.class);
    }

    public IPage<OrderBodyDTO> page(Page<OrderBodyDTO> page, OrderBody model) {
        QueryWrapper<OrderBody> queryWrapper = new QueryWrapper<>(model);
        IPage<OrderBody> iPage = orderBodyRepository.page(page.convert(this::dtoToModel), queryWrapper);
        return iPage.convert(this::modelToDto);
    }


    private void clearCache(OrderBody model) {
        if (null == model) {
            return;
        }
        redisTemplateUtil.deleteByKey(RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getId()));
    }

    public OrderBodyDTO modelToDto(OrderBody model) {
        if (null == model) {
            return null;
        }
        OrderBodyDTO dto = new OrderBodyDTO();
        dto.setId(model.getId());
        dto.setBid(model.getBid());
        dto.setContent(model.getContent());
        dto.setType(model.getType());
        model.freeData();
        return dto;
    }

    public OrderBody dtoToModel(OrderBodyDTO dto) {
        if (null == dto) {
            return null;
        }
        OrderBody model = new OrderBody();
        model.setId(dto.getId());
        model.setBid(dto.getBid());
        model.setContent(dto.getContent());
        model.setType(dto.getType());
        dto.freeData();
        return model;
    }

    public File getCertificate(String appId) {
        return orderBodyRepository.getCertificate(appId);
    }
}